package com.vksyu.beans;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.CellEditEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;
import org.primefaces.model.chart.Axis;
import org.primefaces.model.chart.AxisType;
import org.primefaces.model.chart.CategoryAxis;
import org.primefaces.model.chart.ChartSeries;
import org.primefaces.model.chart.LineChartModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.vksyu.model.CommonData;
import com.vksyu.model.CommonResults;
import com.vksyu.utils.FileUtil;
import com.vksyu.utils.RatingBilder;

@Component
@ManagedBean
@SessionScoped
public class VksyuBean {
	
	@Autowired
	RatingBilder ratingBilder;

	private List<CommonData> commonUniversityData;
	private List<CommonData> commonJournalsData;
	private List<CommonData> universityResults;
	private List<CommonData> jornalsResults;
	private List<CommonResults> commonResults;
	private UploadedFile file;
	private StreamedContent fileForDownload;
	private boolean calculateDisabled = true;
	private boolean downloadDisabled = true;
	private int universityListNumber = 3;
	private int jornalListNumber = 4;
	private LineChartModel resultsModel;
	private final static Logger log = Logger.getLogger(VksyuBean.class.getName());
	
	@PostConstruct
	public void init(){
		resultsModel = new LineChartModel();
	}

	public LineChartModel getResultsModel() {
		return resultsModel;
	}

	public void setResultsModel(LineChartModel resultsModel) {
		this.resultsModel = resultsModel;
	}
	
	public boolean isCalculateDisabled() {
		return calculateDisabled;
	}

	public void setCalculateDisabled(boolean calculateDisabled) {
		this.calculateDisabled = calculateDisabled;
	}

	public boolean isDownloadDisabled() {
		return downloadDisabled;
	}

	public void setDownloadDisabled(boolean downloadDisabled) {
		this.downloadDisabled = downloadDisabled;
	}

	public List<CommonData> getUniversityResults() {
		return universityResults;
	}

	public void setUniversityResults(List<CommonData> universityResults) {
		this.universityResults = universityResults;
	}

	public List<CommonData> getJornalsResults() {
		return jornalsResults;
	}

	public void setJornalsResults(List<CommonData> jornalsResults) {
		this.jornalsResults = jornalsResults;
	}

	public List<CommonResults> getCommonResults() {
		return commonResults;
	}

	public void setCommonResults(List<CommonResults> commonResults) {
		this.commonResults = commonResults;
	}

	public int getUniversityListNumber() {
		return universityListNumber;
	}

	public void setUniversityListNumber(int universityListNumber) {
		this.universityListNumber = universityListNumber;
	}

	public int getJornalListNumber() {
		return jornalListNumber;
	}

	public void setJornalListNumber(int jornalListNumber) {
		this.jornalListNumber = jornalListNumber;
	}

	

	public UploadedFile getFile() {
		return file;
	}

	public List<CommonData> getCommonUniversityData() {
		return commonUniversityData;
	}

	public void setCommonUniversityData(List<CommonData> commonUniversityData) {
		this.commonUniversityData = commonUniversityData;
	}

	public List<CommonData> getCommonJournalsData() {
		return commonJournalsData;
	}

	public void setCommonJournalsData(List<CommonData> commonJournalsData) {
		this.commonJournalsData = commonJournalsData;
	}

	public void setFile(UploadedFile file) {
		this.file = file;
	}

	public void upload() {
		if (file != null && FileUtil.isFileEXEL(file)) {
			if (FileUtil.isFileXLSX(file)) {
				commonUniversityData = FileUtil.readExelSheet(FileUtil
						.createXLSXSheet(file, universityListNumber - 1));
				commonJournalsData = FileUtil.readExelSheet(FileUtil
						.createXLSXSheet(file, jornalListNumber - 1));
			} else {
				commonUniversityData = FileUtil.readExelSheet(FileUtil
						.createXLSSheet(file, universityListNumber - 1));
				commonJournalsData = FileUtil.readExelSheet(FileUtil
						.createXLSSheet(file, jornalListNumber - 1));
			}
			
			calculateDisabled = false;
			FacesMessage message = new FacesMessage("Успішно",
					file.getFileName() + " завантажений.");
			FacesContext.getCurrentInstance().addMessage(null, message);
		} else {
			FacesMessage message = new FacesMessage(
					"Невірний формат файлу, оберіть інший");
			FacesContext.getCurrentInstance().addMessage(null, message);
		}
	}

	public void onUniversityCellEdit(CellEditEvent event) {
		Object oldValue =  event.getOldValue();
		Object newValue =  event.getNewValue();

		CommonData elementToChange = commonUniversityData.get(event
				.getRowIndex());
		
		String collName = event.getColumn().getHeaderText();
		
		if (newValue != null && !newValue.equals(oldValue)) {
			log.info("In the if");
			switch (collName) {
			case "ID":
				log.info("In the case ID");
				elementToChange.setId((Integer)event.getNewValue());
				break;
			case "Назва":
				log.info("In the case name");
				elementToChange.setName((String) event.getNewValue());
				break;
			case "Індекс Якості Науково-педагогічного персоналу":
				log.info("In the case param1");
				elementToChange.setParam1((Double)event.getNewValue());
				break;
			case "Індекс якості навчання":
				log.info("In the case param2");
				elementToChange.setParam2((Double)event.getNewValue());
				break;
			case "Індекс міжнародного визнання":
				log.info("In the case param3");
				elementToChange.setParam3((Double)event.getNewValue());
				break;
			}
				FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
						"Комірка змінена", "З: " + oldValue + ", На:" + newValue);
				FacesContext.getCurrentInstance().addMessage(null, msg);
		}
	}

	public void onJornalsCellEdit(CellEditEvent event) {
		Object oldValue =  event.getOldValue();
		Object newValue =  event.getNewValue();

		CommonData elementToChange = commonJournalsData.get(event
				.getRowIndex());
		
		String collName = event.getColumn().getHeaderText();
		
		if (newValue != null && !newValue.equals(oldValue)) {
			log.info("In the if");
			switch (collName) {
			case "ID":
				log.info("In the case ID");
				elementToChange.setId((Integer)event.getNewValue());
				break;
			case "Назва":
				log.info("In the case name");
				elementToChange.setName((String) event.getNewValue());
				break;
			case "Якість видання":
				log.info("In the case param1");
				elementToChange.setParam1((Double)event.getNewValue());
				break;
			case "Міжнародні індексації":
				log.info("In the case param2");
				elementToChange.setParam2((Double)event.getNewValue());
				break;
			case "Зміст статей":
				log.info("In the case param3");
				elementToChange.setParam3((Double)event.getNewValue());
				break;
			}
				FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
						"Комірка змінена", "З: " + oldValue + ", На:" + newValue);
				FacesContext.getCurrentInstance().addMessage(null, msg);
		}
	}
	
	public void calculate(){
		log.info("IN THE CALCULATE");
		if (commonJournalsData != null && commonUniversityData != null){
			log.info("BOTH LISTS ARE NOT NULL");
			universityResults = ratingBilder.getUniversityRating(commonUniversityData);
			jornalsResults = ratingBilder.getJornalsRating(commonJournalsData);
			commonResults = ratingBilder.getCommonResults(commonUniversityData, commonJournalsData);
			createResultModel();
			log.info("cALCULATING IS FINISHED");
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
					"Успіх", "Рейтинг ВКСЮ обчислено успішно. ");
			FacesContext.getCurrentInstance().addMessage(null, msg);
		} else {
			log.info("SOME LIST IS NULL");
			FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_WARN,
					"Попередження", "Спочатку потрібно завантажити файл. ");
			FacesContext.getCurrentInstance().addMessage(null, msg);
		}
	}
	
	public void createFile(){
		try {
			InputStream stream = FileUtil.getWorkbookInputStream(commonUniversityData,
																	commonJournalsData,
																	universityResults,
																	jornalsResults,
																	commonResults);
			fileForDownload = new DefaultStreamedContent(stream, "file/xls", "VKSYU.xls");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public StreamedContent getFileForDownload() {
		return fileForDownload;
	}
	
	public void reset(){

		downloadDisabled = true;
		calculateDisabled = true;
		
		if (commonUniversityData != null){
			commonUniversityData.clear();
			commonJournalsData.clear();
			resultsModel = new LineChartModel();
			
			if (commonResults != null){
				universityResults.clear();
				jornalsResults.clear();
				commonResults.clear();
			}
			
		}
		
		FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO,
				"INFO", "Форма очищена");
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}
	
	private void createResultModel(){
		resultsModel = initResultModel();
		resultsModel.setTitle("Зміна рейтингу ВКСЮ");
		resultsModel.setLegendPosition("e");
		resultsModel.setShowPointLabels(true);
		resultsModel.getAxes().put(AxisType.X, new CategoryAxis("Id"));
		
		Axis yAxis = resultsModel.getAxis(AxisType.Y);
		
        yAxis.setLabel("ВКСЮ");
        
        List<Double> allVKSYU = new ArrayList<Double>();
        allVKSYU.addAll(RatingBilder.getOnlyVKSYU(universityResults));
        allVKSYU.addAll(RatingBilder.getOnlyVKSYU(jornalsResults));
        allVKSYU.addAll(RatingBilder.getOnlyVKSYUFromResults(commonResults));
        yAxis.setMin(Collections.min(allVKSYU));
        yAxis.setMax(Collections.max(allVKSYU));
	}
	
	private LineChartModel initResultModel(){
		LineChartModel model = new LineChartModel();
		
		ChartSeries universitiesSeries = new ChartSeries();
		universitiesSeries.setLabel("Університети");
		
		ChartSeries jornalsSeries = new ChartSeries();
		jornalsSeries.setLabel("Журнали");
		
		ChartSeries resultsSeries = new ChartSeries();
		resultsSeries.setLabel("Результати");
		
		for (int i = 0; i < commonResults.size(); i++){
			universitiesSeries.set(universityResults.get(i).getId(), universityResults.get(i).getVksyu());
			jornalsSeries.set(jornalsResults.get(i).getId(), jornalsResults.get(i).getVksyu());
			resultsSeries.set(commonResults.get(i).getId(), commonResults.get(i).getVksyu());
		}
		
		model.addSeries(universitiesSeries);
		model.addSeries(jornalsSeries);
		model.addSeries(resultsSeries);
		
		return model;
	}
}
